/**
 * 函数管理路由
 *
 * Created by snowingsea on 2020/03/02.
 */
const middleware = require('./../middleware');
const functions = require('./../../models/functions');
const fileElements = require('./../../models/file-elements');
const PhoenixError = require('./../../models/phoenix-error');

/**
 * 获取文件元素
 * @param req
 * @param res
 * @param next
 */
function getFileElement(req, res, next) {
  let updateUnread = Promise.resolve(req.$fileElement);
  const kind = req.$fileElement.kind || fileElements.elementKind.function;
  if (fileElements.canUpdateUnreadStatus(kind) && req.$fileElement.unread) {
    updateUnread = functions.updateUnread(req.params.fileElementId, false)
      .then(() => functions.getFunction(req.params.fileElementId));
  }
  updateUnread.then((fileElement) => {
    res.json(fileElements.getJson(fileElement));
  }).catch((err) => {
    next(new PhoenixError(err));
  });
}

function resetFileElement(req, res, next) {
  (async () => {
    await fileElements.resetElement(req.params.fileElementId);
    res.status(204).json();
  })().catch((err) => {
    next(new PhoenixError(err));
  });
}

/**
 * 获取文件子元素集合
 * @param req
 * @param res
 * @param next
 */
function getFileElements(req, res, next) {
  const result = {
    pagination: req.filter,
  };
  fileElements.getFileElements(req.params.fileId, req.filter, req.query.kinds)
    .then((data) => {
      result.elements = data.map((func) => fileElements.getSummaryJson(func));
      result.total = data.length;
      res.json(result);
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * 获取文件元素下的树结构
 * @param req
 * @param res
 * @param next
 */
function getFileElementsTree(req, res, next) {
  fileElements.getFileElementsTree(
    req.$fileElement.fileId.toString(),
    req.params.fileElementId,
    req.$fileElement.depth || 1,
    req.query.depth,
    req.query
  ).then((tree) => {
    // append root element
    const resData = {};
    resData.tree = fileElements.getSummaryJson(req.$fileElement);
    resData.tree.children = tree.tree;
    resData.total = tree.total + 1;
    res.json(resData);
  }).catch((err) => {
    next(new PhoenixError(err));
  });
}

/**
 * 元素特化
 * @param req
 * @param res
 * @param next
 */
function specializeElement(req, res, next) {
  fileElements.specializeElement(
    req.$fileElement,
    req.body,
    req.$file,
    req.$project,
    req.$projectVersion
  )
    .then((elementId) => {
      if (!elementId) {
        return res.json({});
      }
      return functions.getFunction(elementId)
        .then((element) => {
          res.json(fileElements.getJson(element));
        });
    })
    .catch((err) => {
      if (err instanceof PhoenixError) {
        return next(err);
      }
      return next(new PhoenixError('invalid request', err.message));
    });
}

function removeSpecialElement(req, res, next) {
  fileElements.removeElement(
    // eslint-disable-next-line no-underscore-dangle
    req.$fileElement._id.toString(),
    req.$fileElement
  )
    .then(() => {
      res.status(204).json();
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

function getSpecializedElements(req, res, next) {
  fileElements.getSpecializedElementsByOriginal(req.$fileElement)
    .then((specializedElements) => {
      res.json(specializedElements.map(
        (specializedElement) => fileElements.getJson(specializedElement)
      ));
    })
    .catch((err) => {
      next(new PhoenixError(err));
    });
}

/**
 * Export model definition object.
 */
module.exports = (app, prefix) => {
  const fileElementURL = `${prefix}/file-elements/:fileElementId.json`;
  const fileElementsURL = `${prefix}/files/:fileId/file-elements.json`;
  const fileElementsTreeURL = `${prefix}/file-elements/:fileElementId/tree.json`;
  const specializedElementsURL = `${prefix}/file-elements/:fileElementId/specialized-elements.json`;
  const fileElementResetURL = `${prefix}/file-elements/:fileElementId/reset.json`;

  // 获取文件元素
  app.get(fileElementURL, middleware.user.requireTokenUnexpired);
  app.get(fileElementURL, middleware.user.requireAvailable);
  app.get(fileElementURL, middleware.user.requireTester);
  app.get(fileElementURL, middleware.fileElement.requireFileElementExist);
  app.get(fileElementURL, middleware.project.requireProjectAccess);
  app.get(fileElementURL, getFileElement);

  // 获取文件下子元素集合
  app.get(fileElementsURL, middleware.user.requireTokenUnexpired);
  app.get(fileElementsURL, middleware.user.requireAvailable);
  app.get(fileElementsURL, middleware.user.requireTester);
  app.get(fileElementsURL, middleware.file.requireFileExist);
  app.get(fileElementsURL, middleware.project.requireProjectAccess);
  app.get(fileElementsURL, middleware.splitFilter);
  app.get(fileElementsURL, getFileElements);

  // 元素特化
  app.post(fileElementsURL, middleware.user.requireTokenUnexpired);
  app.post(fileElementsURL, middleware.user.requireAvailable);
  app.post(fileElementsURL, middleware.user.requireTester);
  app.post(fileElementsURL, middleware.file.requireFileExist);
  app.post(fileElementsURL, middleware.fileElement.requireFileElementExist);
  app.post(fileElementsURL, middleware.fileElement.requireTemplateElement);
  app.post(fileElementsURL, middleware.fileElement.checkDuplicateSpecialization);
  app.post(fileElementsURL, middleware.project.requireProjectAccess);
  app.post(fileElementsURL, middleware.user.getLockByVersion());
  app.post(fileElementsURL, specializeElement);

  // 元素特化删除
  app.delete(fileElementURL, middleware.user.requireTokenUnexpired);
  app.delete(fileElementURL, middleware.user.requireAvailable);
  app.delete(fileElementURL, middleware.user.requireTester);
  app.delete(fileElementURL, middleware.fileElement.requireFileElementExist);
  app.delete(fileElementURL, middleware.fileElement.requireSpecialElement);
  app.delete(fileElementURL, middleware.project.requireProjectAccess);
  app.delete(fileElementURL, middleware.user.getLockByVersion());
  app.delete(fileElementURL, removeSpecialElement);

  // 获取文件元素的树结构
  app.get(fileElementsTreeURL, middleware.user.requireTokenUnexpired);
  app.get(fileElementsTreeURL, middleware.user.requireAvailable);
  app.get(fileElementsTreeURL, middleware.user.requireTester);
  app.get(fileElementsTreeURL, middleware.fileElement.requireFileElementExist);
  app.get(fileElementsTreeURL, middleware.project.requireProjectAccess);
  app.get(fileElementsTreeURL, getFileElementsTree);

  // 获取某个模板元素对应特化出的元素列表
  app.get(specializedElementsURL, middleware.user.requireTokenUnexpired);
  app.get(specializedElementsURL, middleware.user.requireAvailable);
  app.get(specializedElementsURL, middleware.user.requireTester);
  app.get(specializedElementsURL, middleware.fileElement.requireFileElementExist);
  app.get(specializedElementsURL, middleware.fileElement.requireTemplateElement);
  app.get(specializedElementsURL, middleware.project.requireProjectAccess);
  app.get(specializedElementsURL, getSpecializedElements);

  // 获取文件元素
  app.post(fileElementResetURL, middleware.user.requireTokenUnexpired);
  app.post(fileElementResetURL, middleware.user.requireAvailable);
  app.post(fileElementResetURL, middleware.user.requireTester);
  app.post(fileElementResetURL, middleware.fileElement.requireFileElementExist);
  app.post(fileElementResetURL, middleware.project.requireProjectAccess);
  app.post(fileElementResetURL, resetFileElement);
};
